/**
 * ****************************************************************************
 * @file 串口处理模块
 * @note
 * 
 * ****************************************************************************
*/
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "main.h"
#include "uart.h"

static uint8_t UartRxBufferFS[1024];
static volatile uint16_t s_receive_offset = 0;
static volatile uint8_t s_received_flag = 0;

extern DMA_HandleTypeDef hdma_uart1_rx;
extern UART_HandleTypeDef huart1;
/**************************************************
 * @brief 初始化串口
 **************************************************/
void module_uart_init(void)
{
    // 打开 CPU 中断唤醒源
    EXTI_HandleTypeDef hexti;
    EXTI_ConfigTypeDef exticonfig;  
    exticonfig.Line = EXTI_LINE_28;
    exticonfig.Mode = EXTI_MODE_INTERRUPT;  
    HAL_EXTI_SetConfigLine(&hexti,&exticonfig);
    // 设置串口唤醒模式
    UART_WakeUpTypeDef WakeUpSelection = {0};
    WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;
    HAL_UARTEx_StopModeWakeUpSourceConfig(&huart1, WakeUpSelection);
    // 使能串口唤醒中断
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_WUF);
    // 使能串口唤醒标志
    HAL_UARTEx_EnableStopMode(&huart1);
}

/**************************************************
 * @brief 串口接收待处理
 * @return 待处理状态
 **************************************************/
bool module_uart_receive_running(void)
{
    // 数据正在接收或处理
    if (s_received_flag == 1 || __HAL_DMA_GET_COUNTER(huart1.hdmarx) != sizeof(UartRxBufferFS)) {
        return true;
    } else {
        return false;
    }
}

/**************************************************
 * @brief 串口接收处理
 * @param[out] buf 接收数据地址
 * @return 接收数据长度
 **************************************************/
uint16_t module_uart_receive_process(uint8_t *buf)
{
    uint16_t len = 0;
    static uint8_t first_flag = 1;

    if (first_flag == 1) {
        first_flag = 0;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UartRxBufferFS, sizeof(UartRxBufferFS));
        __HAL_DMA_DISABLE_IT(huart1.hdmarx, DMA_IT_HT);
    }

    if (s_received_flag == 1 && s_receive_offset != 0) {
        memcpy(buf, UartRxBufferFS, s_receive_offset);
        memset(UartRxBufferFS, 0, sizeof(UartRxBufferFS));
        len = s_receive_offset;
        s_receive_offset = 0;
        HAL_UART_MspInit(&huart1);
        huart1.RxState = HAL_UART_STATE_READY;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UartRxBufferFS, sizeof(UartRxBufferFS));
        __HAL_DMA_DISABLE_IT(huart1.hdmarx, DMA_IT_HT);
        s_received_flag = 0;
    }

    return len;
}

/**************************************************
 * @brief 串口 DMA 接收退出低功耗重新初始化
 **************************************************/
void module_uart_receive_dma_reinit(void)
{
    if (HAL_DMA_Init(&hdma_uart1_rx) != HAL_OK) {
      Error_Handler();
    }
    __HAL_LINKDMA(&huart1, hdmarx, hdma_uart1_rx);

    UART_Start_Receive_DMA(&huart1, UartRxBufferFS, sizeof(UartRxBufferFS));
    __HAL_DMA_DISABLE_IT(huart1.hdmarx, DMA_IT_HT);
}

/**************************************************
 * @brief 串口接收空闲中断回调函数
 * @note 实现已被HAL库虚定义的函数接口
 * @param[in] huart 串口句柄
 * @param[in] Size 接收到的数据长度
 **************************************************/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    if (huart->Instance == huart1.Instance) {
        s_receive_offset = Size;
        s_received_flag = 1;
    }
}

/**************************************************
 * @brief 串口接收错误中断回调函数
 * @note 实现已被HAL库虚定义的函数接口
 * @param[in] huart 串口句柄
 **************************************************/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == huart1.Instance) {
        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, UartRxBufferFS, sizeof(UartRxBufferFS));
        __HAL_DMA_DISABLE_IT(huart1.hdmarx, DMA_IT_HT);
    }
}

